package com.zq.it.service.validate;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.zq.it.tool.Constant;
import com.zq.it.tool.StringUtil;

/**
 * service层数据校验类
 *
 * @author 王凡
 *
 * @version $ID: Validate.java 2013-4-19 王凡@$
 */
public class Validate<T> {

	private static Document document;

	public boolean validate(T ob) throws VolidateException {
		try {
			boolean flag = false;
			init();
			Element root = document.getRootElement();
			Element entity = null;
			for (Object model : root.elements("entity")) {
				entity = (Element) model;
				if (entity.attributeValue("name")
						.equals(ob.getClass().getName())) {
					flag = true;
					break;
				}
			}
			if (!flag) {
				throw new VolidateException("请检查配置文件！");
			}
			Element column = null;
			Element rule = null;
			for (Object model : entity.elements("column")) {
				column = (Element) model;
				returnTypeValidate(ob, column);
				for (Object ruleModel : column.elements("pram")) {
					rule = (Element) ruleModel;
					if (rule.attributeValue("name").equals("min")) {
						minValidate(ob, column.attributeValue("name"),
								rule.getText());
					} else if (rule.attributeValue("name").equals("max")) {
						maxValidate(ob, column.attributeValue("name"),
								rule.getText());
					} else if (rule.attributeValue("name").equals("value")) {
						valueValidate(ob, column.attributeValue("name"),
								rule.getText());
					} else if (rule.attributeValue("name")
							.equals("DateFormat")) {
						dateFormatValidate(ob, column.attributeValue("name"),
								rule.getText());
					} else if (rule.attributeValue("name").equals("regex")) {
						regexValidate(ob, column.attributeValue("name"),
								rule.getText());
					}
				}
			}
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	private void regexValidate(T ob, String fieldName, String value)
			throws VolidateException {
		try {
			Method method = ob.getClass().getMethod("get" + StringUtil.capitalize(fieldName), null);
			Object str = method.invoke(ob, null);
			if (null != str) {
				Pattern p = Pattern.compile(value);
				if (!p.matcher(str.toString()).matches()) {
					throw new VolidateException("正则表达式校验失败！");
				}
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	private void dateFormatValidate(T ob, String fieldName, String value)
			throws VolidateException {
		try {
			Method method = ob.getClass()
					.getMethod("get" + StringUtil.capitalize(fieldName), null);
			Object date = method.invoke(ob, null);
			if (null != value) {
				try {
					DateFormat df = new SimpleDateFormat(value);
					df.parse(date.toString());
				} catch (ParseException pe) {
					throw new VolidateException("日期格式校验失败！");
				}
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	private void valueValidate(T ob, String fieldName, String valueSet)
			throws VolidateException {
		try {
			Method method = ob.getClass()
					.getMethod("get" + StringUtil.capitalize(fieldName), null);
			Object value = method.invoke(ob, null);
			if (null != value) {
				String[] values = valueSet.split(",");
				boolean flag = false;
				for (String temp : values) {
					if (temp.equals(value.toString())) {
						flag = true;
						break;
					}
				}
				if (!flag) {
					throw new VolidateException("值范围校验失败！");
				}
			} else {
				String[] values = valueSet.split(",");
				boolean flag = false;
				for (String temp : values) {
					if (temp == null || "".equals(temp)) {
						flag = true;
						break;
					}
				}
				if (!flag) {
					throw new VolidateException("值范围校验失败！");
				}
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	private void maxValidate(T ob, String fieldName, String value)
			throws VolidateException {
		try {
			Method method = ob.getClass()
					.getMethod("get" + StringUtil.capitalize(fieldName), null);
			Object max = method.invoke(ob, null);
			if (null != max) {
				if (max.toString().length() > Integer.parseInt(value)) {
					throw new VolidateException("最大长度校验失败！");
				}
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	private void minValidate(T ob, String fieldName, String value)
			throws VolidateException {
		try {
			Method method = ob.getClass()
					.getMethod("get" + StringUtil.capitalize(fieldName), null);
			Object min = method.invoke(ob, null);
			if (null == min
					|| min.toString().length() < Integer.parseInt(value)) {
				throw new VolidateException("最小长度校验失败！");
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	private void returnTypeValidate(T ob, Element column)
			throws VolidateException {
		Method method;
		try {
			method = ob.getClass()
					.getMethod(
							"get" + StringUtil
									.capitalize(column.attributeValue("name")),
							null);
			if (!column.attributeValue("type")
					.equals(method.getReturnType().getName())) {
				throw new VolidateException("类型校验失败！");
			}
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
	}

	private void init() throws DocumentException, UnsupportedEncodingException {
		if (null == document) {
			SAXReader reader = new SAXReader();
			String path = getClass().getClassLoader().getResource(Constant.VALIDATE_XML).getPath();
			path = URLDecoder.decode(path, "utf-8");
			document = reader.read(new File(path));
		}
	}
}
